﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Xml;
using ID3TagLib;

namespace Home.ArtDB
{
    /// <summary>
    /// 
    /// </summary>
    public static class ExtClass
    {

        #region FROM STRING CONVERT METHODS

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static Color ToColor(this string str)
        {
            Color col = Color.Black;
            try
            {
                col = Color.FromName(str);
            }
            catch //(Exception ex)
            {
            }

            return col;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static double ToDouble(this string str)
        {
            double result = 0;

            if (!double.TryParse(str, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str)
        {
            DateTime result = DateTime.MinValue;

            if (!DateTime.TryParse(str, out result))
            {
                result = DateTime.MinValue;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int ToInt(this string str)
        {
            int result = 0;

            if (!int.TryParse(str, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static long ToLong(this string str)
        {
            long result = 0;

            if (!long.TryParse(str, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static ulong ToULong(this string str)
        {
            ulong result = 0;

            if (!ulong.TryParse(str, out result))
            {
                result = 0;
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool ToBool(this string str, bool defaultValue)
        {
            bool result = defaultValue;
            try
            {
                result = Convert.ToBoolean(str);
            }
            catch
            {
            }

            return result;
        }

        #endregion FROM STRING CONVERT METHODS

        #region ENUMERABLE

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string ToString<T>(this IEnumerable<T> source, string separator)
        {
            if (source == null)
                throw new ArgumentException("Parameter source can not be null.");

            if (string.IsNullOrEmpty(separator))
                throw new ArgumentException("Parameter separator can not be null or empty.");

            string[] array = source.Where(n => n != null).Select(n => n.ToString()).ToArray();

            return string.Join(separator, array);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string ToString(this IEnumerable source, string separator)
        {
            if (source == null)
                throw new ArgumentException("Parameter source can not be null.");

            if (string.IsNullOrEmpty(separator))
                throw new ArgumentException("Parameter separator can not be null or empty.");

            string[] array = source.Cast<object>().Where(n => n != null).Select(n => n.ToString()).ToArray();

            return string.Join(separator, array);
        }

        #endregion ENUMERABLE

        #region FROM OBJECT CONVERT METHODS

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool ToBool(this object obj, bool defaultValue)
        {
            return (obj == null) ? defaultValue : obj.ToString().ToBool(defaultValue);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static double ToDouble(this object obj)
        {
            return obj.ToString().ToDouble();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this object obj)
        {
            return obj.ToString().ToDateTime();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int ToInt(this object obj)
        {
            return obj.ToString().ToInt();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static long ToLong(this object obj)
        {
            return obj.ToString().ToLong();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static ulong ToULong(this object obj)
        {
            return obj.ToString().ToULong();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="byteDataSize"></param>
        /// <returns></returns>
        public static string ToFormatDataSize(this object byteDataSize)
        {
            long bytes = byteDataSize.ToLong();

            if (bytes >= 1073741824)
            {
                Decimal size = Decimal.Divide(bytes, 1073741824);
                return String.Format("{0:##.##} GB", size);
            }
            else if (bytes >= 1048576)
            {
                Decimal size = Decimal.Divide(bytes, 1048576);
                return String.Format("{0:##.##} MB", size);
            }
            else if (bytes >= 1024)
            {
                Decimal size = Decimal.Divide(bytes, 1024);
                return String.Format("{0:##.##} KB", size);
            }
            else if (bytes > 0 & bytes < 1024)
            {
                Decimal size = bytes;
                return String.Format("{0:##.##} Bytes", size);
            }
            else
            {
                return "0 Bytes";
            }


            //string ssize = "";
            //if (bytedatasize / 1024 > 1024)
            //{
            //    double size = (bytedatasize / 1024) / 1024;
            //    ssize = size.ToString("#######0.### MB");
            //}
            //else if (bytedatasize > 1024)
            //{
            //    double size = bytedatasize / 1024;
            //    ssize = size.ToString("#######0.### KB");
            //}
            //else
            //{
            //    ssize = bytedatasize.ToString("#######0.### Byte");
            //}
            //return ssize;
        }

        #endregion FROM OBJECT CONVERT METHODS

        #region TIMESTAMP CONVERT METHODS

        /// <summary>
        /// 
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static int ToTimestamp(this DateTime date)
        {
            DateTime date1 = new DateTime(1970, 1, 1);  //Refernzdatum (festgelegt)
            TimeSpan ts = new TimeSpan(date.Ticks - date1.Ticks);  // das Delta ermitteln
            return (Convert.ToInt32(ts.TotalSeconds));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static DateTime ToTimestam(this int timestamp)
        {
            DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
            dateTime = dateTime.AddSeconds(timestamp);
            return dateTime;
        }

        #endregion TIMESTAMP CONVERT METHODS

        #region XMLDOCUMENT


        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="attributename"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int GetTryValue(this XmlNode node, string attributename, int defaultValue)
        {
            int value = defaultValue;
            if (node != null && node.Attributes[attributename] != null)
            {
                string valueString = node.Attributes[attributename].Value;
                if (!int.TryParse(valueString, out value))
                {
                    value = defaultValue;
                }
            }

            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="attributename"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static bool GetTryValue(this XmlNode node, string attributename, bool defaultValue)
        {
            bool value = defaultValue;
            if (node != null && node.Attributes[attributename] != null)
            {
                string valueString = node.Attributes[attributename].Value;
                if (!bool.TryParse(valueString, out value))
                {
                    value = defaultValue;
                }
            }
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="attributename"></param>
        /// <returns></returns>
        public static string GetTryValue(this XmlNode node, string attributename)
        {
            return GetTryValue(node, attributename, "");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="attributename"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetTryValue(this XmlNode node, string attributename, string defaultValue)
        {
            string value = defaultValue;
            if (node != null && node.Attributes[attributename] != null)
            {
                value = node.Attributes[attributename].Value;
            }

            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <param name="attributename"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SetTryValue(this XmlNode node, string attributename, object value)
        {
            bool result = true;
            if (node != null && node.Attributes[attributename] != null)
            {
                if (value is bool)
                {
                    bool val = false;
                    if (bool.TryParse(value.ToString(), out val))
                    {
                        node.Attributes[attributename].Value = val.ToString().ToLower();
                    }
                    else
                    {
                        result = false;
                    }
                }
                else
                {
                    node.Attributes[attributename].Value = value.ToString();
                }
            }
            else
            {
                result = false;
            }

            return result;
        }

        #endregion XMLDOCUMENT

        #region EXCEPTION

        /// <summary>
        /// Alle InnerException in string
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="depth">Tiefe der Rekursion</param>
        /// <returns></returns>
        public static string GetFullExceptionText(this Exception ex, int depth)
        {
            if (ex == null)
                return "";

            string result = ex.Message;
            if (ex.InnerException != null && depth > 0)
            {
                result += "\n\n" + ex.InnerException.Message;
                result += GetFullExceptionText(ex.InnerException, --depth);
            }
            return result;
        }

#endregion EXCEPTION

        /// <summary>
        /// 
        /// </summary>
        /// <param name="frameName"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string Get(this ID3v2Tag v2Tag, string frameName, string defaultValue)
        {
            return (v2Tag.Frames[frameName] != null && !((TextFrame)v2Tag.Frames[frameName]).Text.Length.Equals(0)) ? ((TextFrame)v2Tag.Frames[frameName]).Text : defaultValue;
        }
    }
}
